﻿using Sustainalytics.Auth.Claims;
using Sustainalytics.ClientDW.Entities;
using System;
using System.Collections.Generic;
using System.Security.Claims;

namespace Sustainalytics.GCCS
{
    public static class GCCSUtility
    {
        #region Quarter

        const int CalendarToGccsQuarterMonthsOffset = -1;

        private static DateTime GetFirstWorkingDay(DateTime date)
        {
            return date.DayOfWeek == DayOfWeek.Sunday ? date.AddDays(1) : date.DayOfWeek == DayOfWeek.Saturday ? date.AddDays(2) : date;
        }

        private static int GetQuarter(DateTime date)
        {
            return (date.Month - 1) / 3 + 1;
        }

        private static DateTime GetGccsQuarterStartDate(DateTime date)
        {
            var gccsQuarterStartDate = GetFirstWorkingDay(new DateTime(date.Year, 12, 1));// first working day of December

            if (date >= gccsQuarterStartDate)
            {
                return gccsQuarterStartDate;
            }

            gccsQuarterStartDate = GetFirstWorkingDay(new DateTime(date.Year, 9, 1));// first working day of September

            if (date >= gccsQuarterStartDate)
            {
                return gccsQuarterStartDate;
            }

            gccsQuarterStartDate = GetFirstWorkingDay(new DateTime(date.Year, 6, 1));// first working day of June

            if (date >= gccsQuarterStartDate)
            {
                return gccsQuarterStartDate;
            }

            gccsQuarterStartDate = GetFirstWorkingDay(new DateTime(date.Year, 3, 1));// first working day of March

            if (date >= gccsQuarterStartDate)
            {
                return gccsQuarterStartDate;
            }

            return GetFirstWorkingDay(new DateTime(date.Year - 1, 12, 1));// first working day of December; previous year
        }

        public static DateTime GetGccsQuarterStartDate(GccsQuarter quarter, int year)
        {
            var firstCalendarMonthInQuarter = ((int)quarter - 1) * 3 + 1;

            var quarterCalendarStartDate = new DateTime(year, firstCalendarMonthInQuarter, 1);

            return GetFirstWorkingDay(quarterCalendarStartDate.AddMonths(CalendarToGccsQuarterMonthsOffset));
        }

        public static string GetFormattedGccsQuarter(DateTime gccsQuarterDate, string format)
        {
            var gccsQuarterStartDate = GetGccsQuarterStartDate(gccsQuarterDate);

            var calendarQuarterDate = gccsQuarterStartDate.AddMonths(-CalendarToGccsQuarterMonthsOffset);

            return string.Format(format, GetQuarter(calendarQuarterDate), calendarQuarterDate.Year);
        }

        public static string GetDefaultFormattedGccsQuarter(DateTime gccsQuarterDate)
        {
            string quarter = GetFormattedGccsQuarter(gccsQuarterDate, "Q{0} {1}");
            return quarter;
        }

        #endregion

        #region Universes

        public static List<int> GetUniverses(GCAssessment? overallAssessment)
        {
            var universeIds = GetUniverses(overallAssessment, ClaimsPrincipal.Current.Claims);
            return universeIds;
        }

        public static List<int> GetUniverses(GCAssessment? overallAssessment, IEnumerable<Claim> claims)
        {
            List<int> userUniverseIds;

            switch (overallAssessment)
            {
                case GCAssessment.NonCompliant:
                    userUniverseIds = claims.GetUniverseIds(AccountFeature.GlobalCompactNonCompliant);
                    break;
                case GCAssessment.Watchlist:
                    userUniverseIds = claims.GetUniverseIds(AccountFeature.GlobalCompactWatchlist);
                    break;
                default:
                    {
                        var userUniverseIdsNC = claims.GetUniverseIds(AccountFeature.GlobalCompactNonCompliant);
                        var userUniverseIdsWL = claims.GetUniverseIds(AccountFeature.GlobalCompactWatchlist);

                        userUniverseIds = new List<int>();
                        userUniverseIds.AddRange(userUniverseIdsNC);
                        userUniverseIds.AddRange(userUniverseIdsWL);
                    }
                    break;
            }

            return userUniverseIds;
        }

        #endregion
    }
}
